﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//New and needed
using IM.Domain.Repository;
using IM.Domain.Entities;
using System.Reflection;

namespace IM.Naive
{
    public class RepositoryEntityStore<TEntity>:IRepository<TEntity>
    {
        protected readonly IDictionary<long, TEntity> RepositoryMap = new Dictionary<long, TEntity>();



        #region IRepository<TEntity> Members

        public TEntity Save(TEntity instance)
        {
            IEntity entityInstance = GetEntityInstance(instance);

            if (entityInstance.ID != 0)
            {
                throw new ApplicationException("Entity instance cannot be saved. The ID field was not cero");
            }

            GetNewID(instance);
            RepositoryMap.Add(entityInstance.ID, instance);
            return instance;
        }

        public bool Update(TEntity instance)
        {
            IEntity entityInstance = GetEntityInstance(instance);

            if (entityInstance.ID == 0)
            {
                throw new ApplicationException("The entity instance cannot be updated, the ID field was cero");
            }

            RepositoryMap[entityInstance.ID] = instance;
            return true;
        }

        public bool Delete(TEntity instance)
        {
            IEntity entityInstance = GetEntityInstance(instance);
            return RepositoryMap.Remove(entityInstance.ID);
        }

        public TEntity GetByID(long iD)
        {
            return RepositoryMap[iD];
        }

        public IQueryable<TEntity> GetAll()
        {
            return RepositoryMap.Values.AsQueryable();
        }

        #endregion

        #region Helper methods

        private void GetNewID(TEntity instance)
        {
            GetEntityInstance(instance);
            long max = 0;

            if (RepositoryMap.Count > 0)
            {
                max = RepositoryMap.Keys.Max();
            }

            max = ++max;

            var setter = GetSetter(instance.GetType());
            setter.Invoke(instance, new object[] { max });
        }


        private readonly IDictionary<Type, MethodInfo> Setters = new Dictionary<Type, MethodInfo>();

        private MethodInfo GetSetter(Type type)
        {
            if (this.Setters.ContainsKey(type))
            {
                return this.Setters[type];
            }

            var setter = type.GetProperty("ID").GetSetMethod(true);

            Setters.Add(type, setter);
            return setter;
        }


        private IEntity GetEntityInstance(TEntity instance)
        {
            var entityInstance = instance as IEntity;

            if (entityInstance == null)
            {
                throw new ArgumentException("Passed parameter 'instance' is not an IEntity");
            }
            return entityInstance;
        }
        #endregion
    }
}
